package com.xujie.sportsmeeting.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xujie.sportsmeeting.common.exception.BusinessException;
import com.xujie.sportsmeeting.common.result.ResultCode;
import com.xujie.sportsmeeting.entity.CompetitionEvent;
import com.xujie.sportsmeeting.entity.CompetitionScore;
import com.xujie.sportsmeeting.entity.EventRegistration;
import com.xujie.sportsmeeting.mapper.CompetitionScoreMapper;
import com.xujie.sportsmeeting.service.CompetitionEventService;
import com.xujie.sportsmeeting.service.CompetitionScoreService;
import com.xujie.sportsmeeting.service.EventRegistrationService;
import com.xujie.sportsmeeting.service.EventCheckinService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 比赛成绩服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CompetitionScoreServiceImpl extends ServiceImpl<CompetitionScoreMapper, CompetitionScore> implements CompetitionScoreService {

    private final CompetitionEventService competitionEventService;
    private final EventRegistrationService eventRegistrationService;
    private final EventCheckinService eventCheckinService;

    @Override
    @Transactional
    public boolean recordScore(CompetitionScore score) {
        // 验证项目是否存在
        CompetitionEvent event = competitionEventService.getById(score.getEventId());
        if (event == null) {
            throw new BusinessException(ResultCode.EVENT_NOT_FOUND);
        }

        // 验证报名是否存在且已审核通过
        EventRegistration registration = eventRegistrationService.getById(score.getRegistrationId());
        if (registration == null || registration.getAuditStatus() != 1) {
            throw new BusinessException(ResultCode.REGISTRATION_NOT_FOUND, "报名记录不存在或未审核通过");
        }

        // 验证运动员是否已检录
        boolean isCheckedIn = eventCheckinService.isAthleteCheckedIn(registration.getAthleteId(), score.getEventId());
        if (!isCheckedIn) {
            throw new BusinessException(ResultCode.OPERATION_ERROR, "运动员尚未检录，无法录入成绩");
        }

        // 检查成绩是否已存在
        if (scoreExists(score.getEventId(), score.getAthleteId(), score.getIsFinal())) {
            throw new BusinessException(ResultCode.SCORE_EXISTS);
        }

        // 设置默认值
        score.setRecordTime(LocalDateTime.now());
        score.setStatus(1);
        if (score.getIsFinal() == null) {
            score.setIsFinal(1); // 默认决赛成绩
        }

        // 根据项目类型设置成绩类型
        if (score.getScoreType() == null) {
            score.setScoreType(getDefaultScoreType(event.getEventName()));
        }

        boolean result = save(score);

        // 录入成绩后自动计算排名
        if (result) {
            calculateRankings(score.getEventId(), score.getIsFinal());
        }

        return result;
    }

    @Override
    @Transactional
    public boolean batchRecordScores(List<CompetitionScore> scores) {
        for (CompetitionScore score : scores) {
            recordScore(score);
        }
        return true;
    }

    @Override
    @Transactional
    public boolean updateScore(CompetitionScore score) {
        CompetitionScore existScore = getById(score.getId());
        if (existScore == null) {
            throw new BusinessException(ResultCode.SCORE_NOT_FOUND);
        }

        boolean result = updateById(score);

        // 更新成绩后重新计算排名
        if (result) {
            calculateRankings(existScore.getEventId(), existScore.getIsFinal());
        }

        return result;
    }

    @Override
    public List<CompetitionScore> getEventScores(Long eventId, Integer isFinal) {
        LambdaQueryWrapper<CompetitionScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompetitionScore::getEventId, eventId)
               .eq(CompetitionScore::getStatus, 1);

        if (isFinal != null) {
            wrapper.eq(CompetitionScore::getIsFinal, isFinal);
        }

        wrapper.orderByAsc(CompetitionScore::getRanking)
               .orderByDesc(CompetitionScore::getCreateTime);

        return list(wrapper);
    }

    @Override
    public List<CompetitionScore> getAthleteScores(Long athleteId) {
        LambdaQueryWrapper<CompetitionScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompetitionScore::getAthleteId, athleteId)
               .eq(CompetitionScore::getStatus, 1)
               .orderByDesc(CompetitionScore::getCreateTime);

        return list(wrapper);
    }

    @Override
    @Transactional
    public boolean calculateRankings(Long eventId, Integer isFinal) {
        // 获取项目信息
        CompetitionEvent event = competitionEventService.getById(eventId);
        if (event == null) {
            return false;
        }

        // 获取该项目的所有成绩
        List<CompetitionScore> scores = getEventScores(eventId, isFinal);
        if (scores.isEmpty()) {
            return true;
        }

        // 根据成绩类型排序
        String scoreType = scores.get(0).getScoreType();
        scores.sort((s1, s2) -> compareScores(s1.getScoreValue(), s2.getScoreValue(), scoreType));

        // 计算排名和得分
        AtomicInteger rank = new AtomicInteger(1);
        for (int i = 0; i < scores.size(); i++) {
            CompetitionScore score = scores.get(i);
            
            // 设置排名
            if (i > 0 && compareScores(scores.get(i-1).getScoreValue(), score.getScoreValue(), scoreType) != 0) {
                rank.set(i + 1);
            }
            score.setRanking(rank.get());

            // 计算得分 (前8名得分：9,7,6,5,4,3,2,1)
            BigDecimal points = calculatePoints(rank.get());
            score.setPoints(points);

            // 更新到数据库
            LambdaUpdateWrapper<CompetitionScore> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(CompetitionScore::getId, score.getId())
                        .set(CompetitionScore::getRanking, score.getRanking())
                        .set(CompetitionScore::getPoints, score.getPoints());
            update(updateWrapper);
        }

        return true;
    }

    @Override
    public boolean scoreExists(Long eventId, Long athleteId, Integer isFinal) {
        LambdaQueryWrapper<CompetitionScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompetitionScore::getEventId, eventId)
               .eq(CompetitionScore::getAthleteId, athleteId)
               .eq(CompetitionScore::getStatus, 1);

        if (isFinal != null) {
            wrapper.eq(CompetitionScore::getIsFinal, isFinal);
        }

        return count(wrapper) > 0;
    }

    @Override
    @Transactional
    public boolean deleteScore(Long scoreId) {
        CompetitionScore score = getById(scoreId);
        if (score == null) {
            throw new BusinessException(ResultCode.SCORE_NOT_FOUND);
        }

        boolean result = removeById(scoreId);

        // 删除成绩后重新计算排名
        if (result) {
            calculateRankings(score.getEventId(), score.getIsFinal());
        }

        return result;
    }

    @Override
    public List<CompetitionScore> getTopScores(Long eventId, Integer topN, Integer isFinal) {
        LambdaQueryWrapper<CompetitionScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompetitionScore::getEventId, eventId)
               .eq(CompetitionScore::getStatus, 1);

        if (isFinal != null) {
            wrapper.eq(CompetitionScore::getIsFinal, isFinal);
        }

        wrapper.orderByAsc(CompetitionScore::getRanking)
               .last("LIMIT " + topN);

        return list(wrapper);
    }

    @Override
    public String formatScoreValue(String scoreValue, String scoreType) {
        if (scoreValue == null || scoreValue.trim().isEmpty()) {
            return "";
        }

        try {
            switch (scoreType.toLowerCase()) {
                case "time":
                    // 时间格式：秒.毫秒 -> MM:SS.sss
                    double seconds = Double.parseDouble(scoreValue);
                    int minutes = (int) (seconds / 60);
                    double remainingSeconds = seconds % 60;
                    if (minutes > 0) {
                        return String.format("%d:%06.3f", minutes, remainingSeconds);
                    } else {
                        return String.format("%.3f", remainingSeconds);
                    }
                case "distance":
                    // 距离格式：保留2位小数 + 单位
                    double distance = Double.parseDouble(scoreValue);
                    return String.format("%.2fm", distance);
                case "score":
                    // 分数格式：保留2位小数
                    double points = Double.parseDouble(scoreValue);
                    return String.format("%.2f", points);
                default:
                    return scoreValue;
            }
        } catch (NumberFormatException e) {
            return scoreValue;
        }
    }

    @Override
    public int compareScores(String scoreValue1, String scoreValue2, String scoreType) {
        try {
            double value1 = Double.parseDouble(scoreValue1);
            double value2 = Double.parseDouble(scoreValue2);

            switch (scoreType.toLowerCase()) {
                case "time":
                    // 时间类：越小越好
                    return Double.compare(value1, value2);
                case "distance":
                case "score":
                    // 距离类、分数类：越大越好
                    return Double.compare(value2, value1);
                default:
                    return Double.compare(value1, value2);
            }
        } catch (NumberFormatException e) {
            return scoreValue1.compareTo(scoreValue2);
        }
    }

    /**
     * 根据项目名称推断成绩类型
     */
    private String getDefaultScoreType(String eventName) {
        if (eventName.contains("米") && (eventName.contains("跑") || eventName.contains("接力"))) {
            return "time";
        } else if (eventName.contains("跳") || eventName.contains("投") || eventName.contains("掷")) {
            return "distance";
        } else {
            return "score";
        }
    }

    /**
     * 根据排名计算得分
     */
    private BigDecimal calculatePoints(int ranking) {
        switch (ranking) {
            case 1: return new BigDecimal("9");
            case 2: return new BigDecimal("7");
            case 3: return new BigDecimal("6");
            case 4: return new BigDecimal("5");
            case 5: return new BigDecimal("4");
            case 6: return new BigDecimal("3");
            case 7: return new BigDecimal("2");
            case 8: return new BigDecimal("1");
            default: return BigDecimal.ZERO;
        }
    }
}
